package com.imdroid.carac.services;

import java.util.Date;
import java.util.LinkedList;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.BatteryManager;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.mapapi.utils.DistanceUtil;
import com.baidu.platform.comapi.basestruct.GeoPoint;
import com.imdroid.carac.IMDroid;
import com.imdroid.carac.R;
import com.imdroid.carac.activities.FloatView;
import com.imdroid.carac.activities.Record;
import com.imdroid.carac.activities.SecurityStartupActivity;
import com.imdroid.carac.net.Weibo;
import com.imdroid.carac.process.ProcessFactory;
import com.imdroid.carac.process.UserProcess;

public class SecurityService extends Service {
	/**
	 * The tag of service
	 */
	private static String TAG = "SecurityService";
	/**
	 * The previous battery plugged status
	 */
	private int lastBatteryPluggedStatus = BatteryChangeReceiver.BATTERY_PLUGGED_UNPLUG;
	/**
	 * The battery change receiver
	 */
	private BroadcastReceiver batteryChangeReceiver = new BatteryChangeReceiver();
	/**
	 * the last location
	 */
	private long startLogTime = (new Date()).getTime();
	/**
	 * 短信通知通道
	 */
	private SMSReceiver smsReceiver;
	/**
	 * The location of last send
	 */
	private BDLocation lastSendLocation;
	/**
	 * The time of last send
	 */
	private Date lastSendTime;
	/**
	 * The location listener
	 */
	public BDLocationListener myListener = new MyLocationListener();
	/**
	 * The tag of upload location
	 */
	private boolean uploadLocation = true;
	/**
	 * The linked list
	 */
	private LinkedList<LocationAndTime> locationList = new LinkedList<LocationAndTime>();
	/**
	 * The thread of the detect the sound
	 */
	private LocationUploadThread uploadThread;
	/**
	 * 系统常量
	 */
	private static final int MAX_DISTINANCE_TO_UPLOAD = 300;
	private static final int MAX_TIME_TO_UPLOAD = 30 * 60 * 1000;
	private static final int UPLOAD_THREAD_SIZE = 200;

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Service#onBind(android.content.Intent)
	 */
	public IBinder onBind(Intent intent) {
		Log.d(this.getClass().getSimpleName(), "Security Service on Bind...");
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Service#onStartCommand(android.content.Intent, int, int)
	 */
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d(this.getClass().getSimpleName(),
				"Security Service onStartCommand...");

		super.onStartCommand(intent, flags, startId);
		// 要求地理位置更新记录
		LocationClient locationClient = ((IMDroid) IMDroid.getContext())
				.getLocationClient();
		locationClient.registerLocationListener(myListener);

		// 注册电源变动接收器
		this.registerReceiver(batteryChangeReceiver, new IntentFilter(
				Intent.ACTION_BATTERY_CHANGED));

		// 注册短信通道
		if (smsReceiver == null) {
			smsReceiver = new SMSReceiver();
			Log.d(TAG, "register receiver....");
			IntentFilter intentFilter = new IntentFilter(
					"android.provider.Telephony.SMS_RECEIVED");
			intentFilter.setPriority(Integer.MAX_VALUE);
			this.registerReceiver(smsReceiver, intentFilter);
		}
		// 启动打点上传线程
		if (uploadThread == null) {
			uploadThread = new LocationUploadThread();
			uploadThread.start();
		}
		uploadLocation = true;

		return START_STICKY;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Service#onDestroy()
	 */
	public void onDestroy() {
		Log.d(this.getClass().getSimpleName(), "on destory...");
		// 注销电源变动接收器
		this.unregisterReceiver(batteryChangeReceiver);
		// 注销短信通道
		this.unregisterReceiver(smsReceiver);
		super.onDestroy();
		// 停止打点上传线程
		uploadLocation = false;
		// uploadThread.interrupt();
	}

	/**
	 * The data structure of location and time
	 * 
	 */
	private class LocationAndTime {
		public LocationAndTime(BDLocation location, long logTime) {
			this.location = location;
			this.logTime = logTime;
		}

		public BDLocation location;
		public long logTime;

	}

	/**
	 * The class of battery change recevier
	 * 
	 */
	private class BatteryChangeReceiver extends BroadcastReceiver {
		/**
		 * 
		 */
		private static final int BATTERY_PLUGGED_UNPLUG = 0;
		/**
		 * if need to send the remind SMS to the users
		 */
		private boolean needRemind = true;

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * android.content.BroadcastReceiver#onReceive(android.content.Context,
		 * android.content.Intent)
		 */
		public void onReceive(Context context, Intent intent) {
			int plugged = intent.getIntExtra("plugged", BATTERY_PLUGGED_UNPLUG);
			int batteryLevel = intent.getIntExtra("level", 0);

			SharedPreferences sp = PreferenceManager
					.getDefaultSharedPreferences(IMDroid.getContext());
			Resources resources = IMDroid.getContext().getResources();
			boolean isOpen = sp.getBoolean(
					resources.getString(R.string.KEY_SEC_OPEN), false);

			// 断电时
			if ((lastBatteryPluggedStatus == BatteryManager.BATTERY_PLUGGED_USB || lastBatteryPluggedStatus == BatteryManager.BATTERY_PLUGGED_AC)
					&& plugged == BATTERY_PLUGGED_UNPLUG) {
				Log.d(TAG, "The power is un-plug");
				// 记录是否充电状态
				IMDroid.setBatteryCharge(false);
				// 系统进入防盗模式,如果设备还没有注册则不处理
				if (IMDroid.hasRegister() && isOpen) {
					Intent t = new Intent();
					t.setClass(IMDroid.getContext(),
							SecurityStartupActivity.class);
					t.putExtra("autoBack", true);
					t.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
							| Intent.FLAG_ACTIVITY_CLEAR_TOP);
					IMDroid.getContext().startActivity(t);
				}
				// 断电时，只做基站定位
				startLogTime = (new Date()).getTime();

				// 停止录像
				if (IMDroid.getRecordBackground() && Record.needRecord) {
					Record.pause();
				}
			}

			// 通电时
			if (lastBatteryPluggedStatus == BATTERY_PLUGGED_UNPLUG
					&& (plugged == BatteryManager.BATTERY_PLUGGED_USB || plugged == BatteryManager.BATTERY_PLUGGED_AC)) {
//				Toast.makeText(IMDroid.getContext(), "plug", Toast.LENGTH_SHORT)
//						.show();
				Log.d(TAG, "The power is plug--");
				// 记录是否充电状态
				IMDroid.setBatteryCharge(true);

				startLogTime = (new Date()).getTime();
				// 通电时开始后台录像
				if (IMDroid.getRecordBackground() && Record.needRecord) {
					FloatView.show();
					Record.start();
				}
				// 自动退出安防模式
//				Toast.makeText(IMDroid.getContext(),
//						"instanct + " + SecurityHomeActivity.instance,
//						Toast.LENGTH_SHORT).show();
//				if (SecurityHomeActivity.instance != null) {
//					SecurityHomeActivity.instance.finish();
//				}

				// 通电时自动登录微博
				Weibo.toAuth = true;
			}

			// 判断是否低电量发短信
			if (batteryLevel > 20)
				needRemind = true;
			if (batteryLevel < 19 && needRemind) {
				new Thread() {
					public void run() {
						if (IMDroid.getUser() != null) {
							String phoneNumber = IMDroid.getUser()
									.getMobile_phone();
							String messageText = SecurityService.this
									.getString(R.string.home_battery_not_oka);
							UserProcess process = (UserProcess) ProcessFactory
									.getProcess(UserProcess.class);
							try {
								messageText = messageText.replace("#1#",
										IMDroid.getUser().getNickname());
								process.sendSMS(phoneNumber, messageText);
								needRemind = false;
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					}
				}.start();

			}

			lastBatteryPluggedStatus = plugged;
		}
	}

	/**
	 * The location listener
	 * 
	 */
	private class MyLocationListener implements BDLocationListener {
		// UserProcess userProcess = (UserProcess) ProcessFactory
		// .getProcess(UserProcess.class);

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * com.baidu.location.BDLocationListener#onReceiveLocation(com.baidu
		 * .location.BDLocation)
		 */
		public void onReceiveLocation(final BDLocation arg0) {
			if (arg0 == null)
				return;

			IMDroid.setCurrentLocation(arg0);

			Date now = new Date();
			// 如果间隔时间大于半小时或者距离大于100米的话，发送坐标
			boolean shouldSend = (lastSendLocation == null
					|| lastSendTime == null
					|| getDistance(arg0, lastSendLocation) > MAX_DISTINANCE_TO_UPLOAD || ((new Date())
					.getTime() - lastSendTime.getTime() > MAX_TIME_TO_UPLOAD));

			// 更新坐标
			if (shouldSend) {
				if (locationList.size() <= UPLOAD_THREAD_SIZE) {
					locationList.push(new LocationAndTime(arg0, startLogTime));
				} else {
					locationList.pop();
					locationList.push(new LocationAndTime(arg0, startLogTime));
				}
				lastSendLocation = arg0;
				lastSendTime = now;
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * com.baidu.location.BDLocationListener#onReceivePoi(com.baidu.location
		 * .BDLocation)
		 */
		public void onReceivePoi(BDLocation arg0) {

		}

		/**
		 * @param arg0
		 *            the
		 * @param arg1
		 * @return
		 */
		private long getDistance(BDLocation arg0, BDLocation arg1) {
			GeoPoint gp0 = new GeoPoint((int) (arg0.getLatitude() * 1e6),
					(int) (arg0.getLongitude() * 1e6));
			GeoPoint gp1 = new GeoPoint((int) (arg1.getLatitude() * 1e6),
					(int) (arg1.getLongitude() * 1e6));
			return (long) DistanceUtil.getDistance(gp0, gp1);

		}
	}

	/**
	 * The thread of sending the location - 上传坐标的线程
	 * 
	 */
	private class LocationUploadThread extends Thread {
		UserProcess userProcess = (UserProcess) ProcessFactory
				.getProcess(UserProcess.class);

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Thread#run()
		 */
		public void run() {
			while (uploadLocation) {

				while (locationList.size() > 0) {
					LocationAndTime locationAndTime = locationList.peekFirst();
					if (locationAndTime != null) {
						try {
							Log.d(TAG, "Update location start...size-"
									+ locationList.size());
							userProcess.postUserLocation(
									locationAndTime.location,
									locationAndTime.logTime);

							locationList.remove(locationAndTime);

							Log.d(TAG, "Update location end...size-"
									+ locationList.size());
						} catch (Exception e) {
							Log.d(TAG,
									"Update Fail....size-"
											+ locationList.size());
							break;
						}
					}
				}

				// 暂停10秒钟
				try {
					Thread.sleep(10 * 1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
